package com.model.project;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.TableGenerator;

import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;

import com.core.protocols.IKVObject;
import com.core.utils.LocalizableString;
import com.model.KeyValue;
import com.model.project.attributes.TaskPriority;
import com.model.project.attributes.TaskResolution;
import com.model.project.attributes.TaskStatus;
import com.model.project.attributes.TaskType;
import com.model.user.User;
import com.sun.istack.internal.Nullable;

@Entity
public class ProjectTask
        implements IKVObject {

	private int               id;
	private String            name;
	private String            description;
	private Date              createDate;
	private TaskType          taskType;
	private TaskStatus        taskStatus;
	private TaskResolution    taskResolution;
	private TaskPriority      taskPriority;
	private User              assignee;
	private User              reporter;
	private Version           fixVersion;
	private Version           affectVersion;
	private ProjectTask       parentTask;
	private ProjectItem       parentProject;

	private Set <ProjectTask> subTasks = new HashSet <ProjectTask>();



	public ProjectTask() {

	}



	@ManyToOne
	@Nullable
	@NotFound(action = NotFoundAction.IGNORE)
	public ProjectTask getParentTask () {

		return parentTask;
	}



	public void setParentTask ( ProjectTask parentTask ) {

		this.parentTask = parentTask;
	}



	@ManyToOne(cascade = CascadeType.ALL)
	@Nullable
	@NotFound(action = NotFoundAction.IGNORE)
	public ProjectItem getParentProject () {

		return parentProject;
	}



	public void setParentProject ( ProjectItem parentProject ) {

		this.parentProject = parentProject;
	}



	@Override
	public void assignTo ( IKVObject object ) {

		if ( object == null ) {
			return;
		}

		ProjectTask objectToUpdate = (ProjectTask) object;
		objectToUpdate.name = this.name;
		objectToUpdate.description = this.description;
		objectToUpdate.createDate = this.createDate;
		objectToUpdate.taskType = this.taskType;
		objectToUpdate.taskStatus = this.taskStatus;
		objectToUpdate.taskResolution = this.taskResolution;
		objectToUpdate.taskPriority = this.taskPriority;
		objectToUpdate.assignee = this.assignee;
		objectToUpdate.reporter = this.reporter;
		objectToUpdate.fixVersion = this.fixVersion;
		objectToUpdate.affectVersion = this.affectVersion;

	}



	@Id
	@TableGenerator(allocationSize = 10, table = "Generators", pkColumnName = "generatorName", pkColumnValue = "generatorProjectTask", name = "generatorProjectTask")
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "generatorProjectTask")
	public Integer getId () {

		return id;
	}



	public void setId ( int id ) {

		this.id = id;
	}



	public String getName () {

		return name;
	}



	public void setName ( String name ) {

		this.name = name;
	}



	@Lob
	public String getDescription () {

		return description;
	}



	public void setDescription ( String description ) {

		this.description = description;
	}



	@OneToMany(cascade = CascadeType.ALL)
	@JoinTable(name = "projecttask_tasks", joinColumns = {
		@JoinColumn(name = "PARENT_TASK_ID")
	}, inverseJoinColumns = {
		@JoinColumn(name = "TASK_ID")
	})
	public Set <ProjectTask> getSubTasks () {

		return this.subTasks;
	}



	public void setSubTasks ( Set <ProjectTask> subTasks ) {

		this.subTasks = subTasks;
	}



	public Date getCreateDate () {

		return createDate;
	}



	public void setCreateDate ( Date createDate ) {

		this.createDate = createDate;
	}



	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@NotFound(action = NotFoundAction.IGNORE)
	@JoinColumn(nullable = true, updatable = true)
	public TaskType getTaskType () {

		return taskType;
	}



	public void setTaskType ( TaskType taskType ) {

		this.taskType = taskType;
	}



	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@NotFound(action = NotFoundAction.IGNORE)
	@JoinColumn(nullable = true, updatable = true)
	public TaskStatus getTaskStatus () {

		return taskStatus;
	}



	public void setTaskStatus ( TaskStatus taskStatus ) {

		this.taskStatus = taskStatus;
	}



	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@NotFound(action = NotFoundAction.IGNORE)
	@JoinColumn(nullable = true, updatable = true)
	public TaskResolution getTaskResolution () {

		return taskResolution;
	}



	public void setTaskResolution ( TaskResolution taskResolution ) {

		this.taskResolution = taskResolution;
	}



	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@NotFound(action = NotFoundAction.IGNORE)
	@JoinColumn(nullable = true, updatable = true)
	public TaskPriority getTaskPriority () {

		return taskPriority;
	}



	public void setTaskPriority ( TaskPriority taskPriority ) {

		this.taskPriority = taskPriority;
	}



	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@NotFound(action = NotFoundAction.IGNORE)
	@JoinColumn(nullable = true, updatable = true)
	public User getAssignee () {

		return assignee;
	}



	public void setAssignee ( User assignee ) {

		this.assignee = assignee;
	}



	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@NotFound(action = NotFoundAction.IGNORE)
	@JoinColumn(nullable = true, updatable = true)
	public User getReporter () {

		return reporter;
	}



	public void setReporter ( User reporter ) {

		this.reporter = reporter;
	}



	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@NotFound(action = NotFoundAction.IGNORE)
	@JoinColumn(nullable = true, updatable = true)
	public Version getAffectVersion () {

		return affectVersion;
	}



	public void setAffectVersion ( Version affectVersion ) {

		this.affectVersion = affectVersion;
	}



	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@NotFound(action = NotFoundAction.IGNORE)
	@JoinColumn(nullable = true, updatable = true)
	public Version getFixVersion () {

		return fixVersion;
	}



	public void setFixVersion ( Version fixVersion ) {

		this.fixVersion = fixVersion;
	}



	@Override
	public KeyValue idValue () {

		String strIdValue = this.getId().toString();
		return new KeyValue(this.fieldNameAsId(), strIdValue, false);

	}



	@Override
	public String fieldNameAsId () {

		return "id";
	}



	@Override
	public KeyValue nameValue () {

		String strIdValue = this.getName().toString();
		return new KeyValue(this.fieldNameAsName(), strIdValue, false);

	}



	@Override
	public String fieldNameAsName () {

		return "name";
	}



	public String localizableDescription () {

		return LocalizableString.sharedInstance().localizable("entity.ProjectTask.description");

	}
}
